package lifecycle

import (
	"fmt"
	"time"
)

// SupervisionDirective 表示监督指令
type SupervisionDirective int

const (
	// SupervisionDirectiveRestart 表示重启Actor
	SupervisionDirectiveRestart SupervisionDirective = iota
	// SupervisionDirectiveResume 表示恢复Actor
	SupervisionDirectiveResume
	// SupervisionDirectiveStop 表示停止Actor
	SupervisionDirectiveStop
	// SupervisionDirectiveEscalate 表示将错误上报给上级监督者
	SupervisionDirectiveEscalate
)

// String 返回监督指令的字符串表示
func (d SupervisionDirective) String() string {
	switch d {
	case SupervisionDirectiveRestart:
		return "restart"
	case SupervisionDirectiveResume:
		return "resume"
	case SupervisionDirectiveStop:
		return "stop"
	case SupervisionDirectiveEscalate:
		return "escalate"
	default:
		return "unknown"
	}
}

// SupervisionStrategy 表示监督策略接口
type SupervisionStrategy interface {
	// HandleFailure 处理Actor失败
	HandleFailure(actor *LifecycleAwareActor, err error) SupervisionDirective
}

// OneForOneStrategy 表示一对一监督策略
type OneForOneStrategy struct {
	// MaxRetries 是最大重试次数
	MaxRetries int
	// RetryWindow 是重试窗口时间
	RetryWindow time.Duration
	// BackoffFactor 是退避因子
	BackoffFactor float64
	// MaxBackoff 是最大退避时间
	MaxBackoff time.Duration
	// retryCount 是当前重试次数
	retryCount int
	// lastRetryTime 是上次重试时间
	lastRetryTime time.Time
}

// NewOneForOneStrategy 创建一个新的一对一监督策略
func NewOneForOneStrategy(maxRetries int, retryWindow time.Duration, backoffFactor float64, maxBackoff time.Duration) *OneForOneStrategy {
	return &OneForOneStrategy{
		MaxRetries:    maxRetries,
		RetryWindow:   retryWindow,
		BackoffFactor: backoffFactor,
		MaxBackoff:    maxBackoff,
		retryCount:    0,
		lastRetryTime: time.Time{},
	}
}

// HandleFailure 处理Actor失败
func (s *OneForOneStrategy) HandleFailure(actor *LifecycleAwareActor, err error) SupervisionDirective {
	// 检查是否超过最大重试次数
	if s.MaxRetries >= 0 && s.retryCount >= s.MaxRetries {
		// 重置重试计数
		s.retryCount = 0
		return SupervisionDirectiveStop
	}

	// 检查是否在重试窗口内
	now := time.Now()
	if !s.lastRetryTime.IsZero() && now.Sub(s.lastRetryTime) > s.RetryWindow {
		// 重置重试计数
		s.retryCount = 0
	}

	// 增加重试计数
	s.retryCount++
	s.lastRetryTime = now

	// 计算退避时间
	backoff := time.Duration(float64(time.Second) * s.BackoffFactor * float64(s.retryCount))
	if backoff > s.MaxBackoff {
		backoff = s.MaxBackoff
	}

	// 等待退避时间
	time.Sleep(backoff)

	return SupervisionDirectiveRestart
}

// AllForOneStrategy 表示全体监督策略
type AllForOneStrategy struct {
	// OneForOneStrategy 是基础策略
	OneForOneStrategy
}

// NewAllForOneStrategy 创建一个新的全体监督策略
func NewAllForOneStrategy(maxRetries int, retryWindow time.Duration, backoffFactor float64, maxBackoff time.Duration) *AllForOneStrategy {
	return &AllForOneStrategy{
		OneForOneStrategy: *NewOneForOneStrategy(maxRetries, retryWindow, backoffFactor, maxBackoff),
	}
}

// Supervisor 表示Actor监督者
type Supervisor struct {
	// Strategy 是监督策略
	Strategy SupervisionStrategy
	// Children 是子Actor列表
	Children []*LifecycleAwareActor
}

// NewSupervisor 创建一个新的监督者
func NewSupervisor(strategy SupervisionStrategy) *Supervisor {
	return &Supervisor{
		Strategy: strategy,
		Children: make([]*LifecycleAwareActor, 0),
	}
}

// AddChild 添加子Actor
func (s *Supervisor) AddChild(actor *LifecycleAwareActor) {
	s.Children = append(s.Children, actor)
}

// RemoveChild 移除子Actor
func (s *Supervisor) RemoveChild(actor *LifecycleAwareActor) {
	for i, child := range s.Children {
		if child == actor {
			s.Children = append(s.Children[:i], s.Children[i+1:]...)
			return
		}
	}
}

// HandleFailure 处理子Actor失败
func (s *Supervisor) HandleFailure(actor *LifecycleAwareActor, err error) error {
	directive := s.Strategy.HandleFailure(actor, err)

	switch directive {
	case SupervisionDirectiveRestart:
		// 停止Actor
		if actor.IsRunning() || actor.IsPaused() {
			if err := actor.OnStop(); err != nil {
				return fmt.Errorf("failed to stop actor: %w", err)
			}
		}
		// 重置状态为初始化
		actor.State = LifecycleStateInitialized
		// 启动Actor
		if err := actor.OnStart(); err != nil {
			return fmt.Errorf("failed to start actor: %w", err)
		}
	case SupervisionDirectiveResume:
		// 恢复Actor
		if actor.IsPaused() {
			if err := actor.OnResume(); err != nil {
				return fmt.Errorf("failed to resume actor: %w", err)
			}
		}
	case SupervisionDirectiveStop:
		// 停止Actor
		if actor.IsRunning() || actor.IsPaused() {
			if err := actor.OnStop(); err != nil {
				return fmt.Errorf("failed to stop actor: %w", err)
			}
		}
	case SupervisionDirectiveEscalate:
		// 上报错误，这里简单地返回错误
		return fmt.Errorf("escalated error: %w", err)
	}

	return nil
}
